import axios from 'axios'
import store from '@/store'
import { message } from 'ant-design-vue'
const request = axios.create({})
const validateStatus = (status: number) => {
  return status >= 200 && status < 300
}
//配置公用路径
request.defaults.baseURL = process.env.NODE_ENV === 'production' ? '' : '/apis'
//响应时间
request.defaults.timeout = 6000
// 请求拦截器
request.interceptors.request.use(
  function(config) {
    // 我们就在这里通过改写 config 配置信息来实现业务功能的统一处理
    const { user } = store.state
    if (user && user.token) {
      config.headers.token = user.token
    }
    return config
  },
  function(error) {
    // 错误异常处理
    return Promise.reject(error)
  }
)

// 响应拦截器
let isRfreshing = false // 控制刷新 token 的状态
let requests: (() => void)[] = [] // 存储刷新 token 期间过来的 401 请求
request.interceptors.response.use(
  function(response) {
    // 状态码为 2xx 都会进入这里
    // console.log('请求响应成功了 => ', response)
    // 如果是自定义错误状态码，错误处理就写到这里
    const { msg, code } = response?.data
    if (!validateStatus(code) && code !== undefined) {
      //返回错误状态
      return Promise.reject(msg)
    }
    const res = response?.data
    return !res?.data ? res : res?.data
  },
  async function(error) {
    // 超出 2xx 状态码都都执行这里
    // 如果是使用的 HTTP 状态码，错误处理就写到这里
    if (error.response) {
      // 请求发出去收到响应了，但是状态码超出了 2xx 范围
      const { status } = error.response
      if (status === 400) {
        message.error('请求参数错误')
      } else if (status === 401) {
        // token 无效（没有提供 token、token 是无效的、token 过期了）
        // 如果有 refreshToken 则尝试使用 refreshToken 获取新的 access_token
        if (!store.state.user || !store.state.user?.refreshToken) {
          message.warning('登录已过期，请重新登录')
          store.commit('setUser', null)
          store.commit('setMenu', [])
          // 跳转到登录页面
          return Promise.reject(error)
        }
        // 刷新 token
        if (!isRfreshing) {
          isRfreshing = true // 开启刷新状态
          // 尝试刷新获取新的 token
          return request
            .get('/sso/app/refresh/token/' + store.state.user?.refreshToken)
            .then(res => {
              // 刷新 token 成功了
              store.state.user.token = res.data
              // 把 requests 队列中的请求重新发出去
              requests.forEach(cb => cb())
              // 重置 requests 数组
              requests = []
              return request(error.config)
            })
            .catch(() => {
              // 跳转到登录页面
              message.warning('登录已过期，请重新登录')
              store.commit('setUser', null)
              store.commit('setMenu', [])
              return Promise.reject(error)
            })
            .finally(() => {
              isRfreshing = false // 重置刷新状态
            })
        }
        // 刷新状态下，把请求挂起放到 requests 数组中
        return new Promise(resolve => {
          requests.push(() => {
            resolve(request(error.config))
          })
        })
      } else if (status === 403) {
        message.error('没有权限，请联系管理员')
      } else if (status === 404) {
        message.error('请求资源不存在')
      } else if (status >= 500) {
        message.error('服务端错误，请联系管理员')
      }
    } else if (error.request) {
      // 请求发出去没有收到响应
      message.error('请求超时，请刷新重试')
    } else {
      // 在设置请求时发生了一些事情，触发了一个错误
      message.error(`请求失败：${error.message}`)
    }
    // 把请求失败的错误对象继续抛出，扔给上一个调用者
    return Promise.reject(error)
  }
)

export default request
